#pragma once

#include <iostream>
#include <queue>
#include <pthread.h>

using namespace std;

template <class T>
class Blockqueue
{
    static const int defalutnum = 20; // 阻塞队列最大容量
public:
    Blockqueue(int maxcap = defalutnum)
        : _maxcap(maxcap)
    {
        pthread_mutex_init(&_lock, nullptr);
        pthread_cond_init(&c_cond, nullptr);
        pthread_cond_init(&p_cond, nullptr);

        //low_water=_maxcap/3;
        //high_water=(_maxcap*2)/3;
    }

    ~Blockqueue()
    {
        pthread_mutex_destroy(&_lock);
        pthread_cond_destroy(&c_cond);
        pthread_cond_destroy(&p_cond);
    }

    // 生产
    void push(T val)
    {
        pthread_mutex_lock(&_lock);
        while (_q.size() == _maxcap)    //使用while 防止“伪唤醒”的状况 当条件变量中有多个线程，我们唤醒所有生产线程，此时阻塞队列是满的，多个生产线程竞争到锁后生产，出现溢出的情况
        {
            pthread_cond_wait(&p_cond, &_lock);
        }
        _q.push(val);
        //if(_q.size()>high_water)  pthread_cond_broadcast(&c_cond);
        pthread_cond_signal(&c_cond);
        pthread_mutex_unlock(&_lock);
    }

    // 消费
    T pop()
    {
        pthread_mutex_lock(&_lock);
        while (_q.size() == 0)
        {
            pthread_cond_wait(&c_cond, &_lock);
        }
        T top = _q.front();
        _q.pop();
        //if(_q.size()<low_water)  pthread_cond_broadcast(&p_cond);
        pthread_cond_signal(&p_cond);
        pthread_mutex_unlock(&_lock);

        return top;
    }

private:
    std::queue<T> _q;
    int _maxcap; // 极值
    pthread_mutex_t _lock;
    pthread_cond_t c_cond;
    pthread_cond_t p_cond;

    //int low_water;
    //int high_water;
};